//
//  YanStatusListViewModel.swift
//  SinaWeibo
//
//  Created by mac on 2017/5/4.
//  Copyright © 2017年 mac. All rights reserved.
//

import Foundation
import SDWebImage

/// 微博数据列表试图模型
/*
 父类的选择
 
 - 如果类需要使用 ‘KVC’ 或者字典转模型框架设置对象值，类就需要继承 NSObject
 - 如果类只是包装一些代码逻辑（写一些函数）,可以不用任何父类，好处：更加轻量级
 - 提示：如果用OC写，一律都继承自NSObject即可
 
 使命：负责微博的数据处理
 1.字典转模型
 2.下拉、上拉刷新数据处理
*/

/// 上拉刷新最大尝试次数
private let maxPullupTryTime = 3

class YanStatusListViewModel {
    
    /// 微博模型数组懒加载
    lazy var statusList = [YanStatusViewModel]()
    
    private var pullupErrorTimes = 0
    
    /// 加载微博列表
    ///
    /// - Parameters:
    ///   - pullup: 是否上拉刷新标记
    ///   - completion: 完成回调
    func loadStatus(pullup: Bool, completion: @escaping (_ isSuccess: Bool, _ hasMorePullup: Bool)->()) {
        
        // 判断是否是上拉刷新,同时检查刷新错误
        if pullup && pullupErrorTimes > maxPullupTryTime {
            completion(true,false)
            
            return
        }
        
        /// 去除数组中第一条微博的id
        let since_id = pullup ? 0 : (statusList.first?.status.id ?? 0)
        /// 上拉刷新，去除数组的最后一条微博的is
        let max_id = !pullup ? 0 : (statusList.last?.status.id ?? 0)
        
        
        YanNetworkManager.shared.statusList(since_id: since_id, max_id: max_id) { (list, isSuccess) in
            
            // 0.判断网络请求是否成功
            if !isSuccess {
                completion(false,false)
                
                return
            }
            
            // 1.字典转模型
            
            // 1> 定义结果可变数组
            var array = [YanStatusViewModel]()
            // 2> 遍历服务器返回的字典数组，字典转模型
            for dict in list {
                // a) 创建微博模型
                guard let model = YanStatus.yy_model(with: dict) else {
                    continue
                }
                
                // b) 将试图模型添加到数组
                array.append(YanStatusViewModel(model: model))
            }
            
//            guard let array = NSArray.yy_modelArray(with: YanStatus.self, json: list) as? [YanStatus] else {
//                
//                completion(isSuccess,false)
//                
//                return
//            }
//            

            // 2.拼接数据
            if pullup {
                self.statusList += array
            } else {
                self.statusList = array + self.statusList
            }
            // 3.判断上拉刷新的数据量
            if pullup && array.count == 0 {
                self.pullupErrorTimes += 1
                completion(isSuccess, false)
            } else {
                self.cacheSingelImage(list: array, finished: completion)
                
                // 4.完成回调
//                completion(isSuccess,true)
            }
            
        }
        
    }
    
    /// 缓存本次下载微博数据数组中的单张图像
    /// - 应该缓存完单张图像，并且修改过配图的大小之后再回调，才能保证表格等比例显示单张图像
    /// - Parameter list: 本次下载的师徒模型数组
    fileprivate func cacheSingelImage(list: [YanStatusViewModel], finished: @escaping (_ isSuccess: Bool, _ hasMorePullup: Bool)->()) {
        
        // 调度组
        let group = DispatchGroup()
        
        // 记录数据长度
        var length = 0
        
        // 遍历数组 查询微博数据中有单张图像的，进行缓存
        for vm in list {
            // 1.判断图像数量
            if vm.picURLs?.count != 1 {
                continue
            }
            
            // 2.获取 图像模型
            guard let pic = vm.picURLs![0].thumbnail_pic,
                let url = URL(string: pic) else {
                    continue
            }
            
            // 3.下载图像
            // 1) downloadImage 是 SDWebImage 的核心方法
            // 2) 图像下载完成之后，会自动保存在沙盒中，文件路径是 URL 的md5
            // 3) 如果沙盒中已经存在缓存的图像，后续使用 SD 通过 URL 加载图像，都会加载本地沙盒的图像
            // 如果要缓存的图像累计很大，要后台要接口
            
            // A> 入组
            group.enter()
            
            _ = SDWebImageManager.shared().imageDownloader?.downloadImage(with: url, options: [], progress: nil, completed: { (image, _, _, _) in
                // 将图像转换成二进制数据
                if let image = image,
                    let data = UIImagePNGRepresentation(image) {
                    length += data.count
                    
                    vm.updateSingleImageSize(image: image)
                }
                // B> 出组
                group.leave()
            })
            
        }
        
        // C> 监听调度组情况
        group.notify(queue: DispatchQueue.main) {
            print("图像缓存完成 \(length / 1024) K")
            
            // 执行闭包回调
            finished(true, true)
        }
    }
}
